/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.mzba.zxdlyllp.widget;

import android.content.Context;
import android.widget.Scroller;

/**
 * Provides access to new {@link android.widget.Scroller Scroller} APIs when
 * available.
 * 
 * <p>
 * This class provides a platform version-independent mechanism for obeying the
 * current device's preferred scroll physics and fling behavior. It offers a
 * subset of the APIs from Scroller or OverScroller.
 * </p>
 */
class ScrollerCompat {
	Scroller mScroller;

	static class ScrollerCompatImplIcs extends ScrollerCompat {
		public ScrollerCompatImplIcs(Context context) {
			super(context);
		}

		@Override
		public float getCurrVelocity() {
			return ScrollerCompatIcs.getCurrVelocity(mScroller);
		}
	}

	public static ScrollerCompat from(Context context) {
		if (android.os.Build.VERSION.SDK_INT >= 14) {
			return new ScrollerCompatImplIcs(context);
		}
		return new ScrollerCompat(context);
	}

	ScrollerCompat(Context context) {
		mScroller = new Scroller(context);
	}

	/**
	 * Returns whether the scroller has finished scrolling.
	 * 
	 * @return True if the scroller has finished scrolling, false otherwise.
	 */
	public boolean isFinished() {
		return mScroller.isFinished();
	}

	/**
	 * Returns how long the scroll event will take, in milliseconds.
	 * 
	 * @return The duration of the scroll in milliseconds.
	 */
	public int getDuration() {
		return mScroller.getDuration();
	}

	/**
	 * Returns the current X offset in the scroll.
	 * 
	 * @return The new X offset as an absolute distance from the origin.
	 */
	public int getCurrX() {
		return mScroller.getCurrX();
	}

	/**
	 * Returns the current Y offset in the scroll.
	 * 
	 * @return The new Y offset as an absolute distance from the origin.
	 */
	public int getCurrY() {
		return mScroller.getCurrY();
	}

	/**
	 * Returns the current velocity.
	 * 
	 * TODO: Approximate a sane result for older platform versions. Right now
	 * this will return 0 for platforms earlier than ICS. This is acceptable at
	 * the moment only since it is only used for EdgeEffect, which is also only
	 * present in ICS+, and ScrollerCompat is not public.
	 * 
	 * @return The original velocity less the deceleration. Result may be
	 *         negative.
	 */
	public float getCurrVelocity() {
		return 0;
	}

	/**
	 * Call this when you want to know the new location. If it returns true, the
	 * animation is not yet finished. loc will be altered to provide the new
	 * location.
	 */
	public boolean computeScrollOffset() {
		return mScroller.computeScrollOffset();
	}

	/**
	 * Start scrolling by providing a starting point and the distance to travel.
	 * The scroll will use the default value of 250 milliseconds for the
	 * duration.
	 * 
	 * @param startX
	 *            Starting horizontal scroll offset in pixels. Positive numbers
	 *            will scroll the content to the left.
	 * @param startY
	 *            Starting vertical scroll offset in pixels. Positive numbers
	 *            will scroll the content up.
	 * @param dx
	 *            Horizontal distance to travel. Positive numbers will scroll
	 *            the content to the left.
	 * @param dy
	 *            Vertical distance to travel. Positive numbers will scroll the
	 *            content up.
	 */
	public void startScroll(int startX, int startY, int dx, int dy) {
		mScroller.startScroll(startX, startY, dx, dy);
	}

	/**
	 * Start scrolling by providing a starting point and the distance to travel.
	 * 
	 * @param startX
	 *            Starting horizontal scroll offset in pixels. Positive numbers
	 *            will scroll the content to the left.
	 * @param startY
	 *            Starting vertical scroll offset in pixels. Positive numbers
	 *            will scroll the content up.
	 * @param dx
	 *            Horizontal distance to travel. Positive numbers will scroll
	 *            the content to the left.
	 * @param dy
	 *            Vertical distance to travel. Positive numbers will scroll the
	 *            content up.
	 * @param duration
	 *            Duration of the scroll in milliseconds.
	 */
	public void startScroll(int startX, int startY, int dx, int dy, int duration) {
		mScroller.startScroll(startX, startY, dx, dy, duration);
	}

	/**
	 * Start scrolling based on a fling gesture. The distance travelled will
	 * depend on the initial velocity of the fling.
	 * 
	 * @param startX
	 *            Starting point of the scroll (X)
	 * @param startY
	 *            Starting point of the scroll (Y)
	 * @param velocityX
	 *            Initial velocity of the fling (X) measured in pixels per
	 *            second.
	 * @param velocityY
	 *            Initial velocity of the fling (Y) measured in pixels per
	 *            second
	 * @param minX
	 *            Minimum X value. The scroller will not scroll past this point.
	 * @param maxX
	 *            Maximum X value. The scroller will not scroll past this point.
	 * @param minY
	 *            Minimum Y value. The scroller will not scroll past this point.
	 * @param maxY
	 *            Maximum Y value. The scroller will not scroll past this point.
	 */
	public void fling(int startX, int startY, int velocityX, int velocityY,
			int minX, int maxX, int minY, int maxY) {
		mScroller.fling(startX, startY, velocityX, velocityY, minX, maxX, minY,
				maxY);
	}

	/**
	 * Stops the animation. Contrary to {@link #forceFinished(boolean)},
	 * aborting the animating cause the scroller to move to the final x and y
	 * position
	 */
	public void abortAnimation() {
		mScroller.abortAnimation();
	}
}
